﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace Socket服务端队列缓存
{
    internal class Program
    {
        //线程安全的字典
        private static ConcurrentDictionary<int, SocketClient> clients = new ConcurrentDictionary<int, SocketClient>();
        //线程安全的队列（先进先出）
        private static ConcurrentQueue<QueuedMessage> messageQueue = new ConcurrentQueue<QueuedMessage>();
        private static int clientIdCounter = 0;

        static void Main(string[] args)
        {
            TcpService service = new TcpService();
            //服务端的初始化配置
            service.Setup(new TouchSocketConfig()
                .SetListenIPHosts(new IPHost[]{ new IPHost(System.Net.IPAddress.Any,50000) })
                .SetMaxCount(200))
                .Start();

            service.Connected += ClientConnected;
            service.Received += ClientReceived;

            //单独开线程给队列里的客户端发送消息
            Task.Run(() => ProcessQueue());

            Console.WriteLine("Server started. Press any key to exit...");
            Console.ReadKey();
        }

        private static void ClientConnected(SocketClient client, TouchSocketEventArgs e)
        {
            //线程安全的自增ID
            int clientId = System.Threading.Interlocked.Increment(ref clientIdCounter);
            //往线程安全的字典里加入数据
            clients.TryAdd(clientId, client);
            Console.WriteLine($"Client {clientId} connected.");
        }

        private static void ClientReceived(SocketClient client, ByteBlock byteBlock, object obj)
        {
            string message = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);

            //对接收的数据进行处理


            //将当前的客户端和数据加入队列
            messageQueue.Enqueue(new QueuedMessage(client, $"Response to your message: {message}"));
        }

        private static async Task ProcessQueue()
        {
            while (true)
            {
                //从队列中取出
                while (messageQueue.TryDequeue(out QueuedMessage queuedMessage))
                {
                    queuedMessage.Client.Send(Encoding.UTF8.GetBytes(queuedMessage.Message));
                }
                await Task.Delay(100); // 等待
            }
        }

        class QueuedMessage
        {
            public SocketClient Client { get; }
            public string Message { get; }

            public QueuedMessage(SocketClient client, string message)
            {
                Client = client;
                Message = message;
            }
        }
    }
}
